{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Playing text-based games with TextWorld\n",
    "This tutorial shows how to play a text-based adventure game using TextWorld's API."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Playing Zork1\n",
    "### Getting the game file\n",
    "First, we need a copy of `zork1.z5`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading zork1.z5 ...\n",
      "Done.\n"
     ]
    }
   ],
   "source": [
    "!echo \"Downloading zork1.z5 ...\"\n",
    "!wget -q -N https://archive.org/download/Zork1Release88Z-machineFile/zork1.z5\n",
    "!echo \"Done.\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Loading the library"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import textworld"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Documentation for the TextWorld API can be found at\n",
    "\n",
    "https://textworld-docs.azurewebsites.net/textworld.html"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Starting a game"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "env = textworld.start('./zork1.z5')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here `env` is a subclass of `textworld.core.Environment`. It provides the API allowing us to interact with the text-based game parser/interpreter that is running `zork1.z5`. Here are the most important methods we can access:\n",
    "\n",
    "```python\n",
    "# Restart the game and get the initial observation/state from the game.\n",
    "game_state = env.reset()\n",
    "\n",
    "# Some games contain stochasticity, the following allows us to make a playthrough reproducible.\n",
    "env.seed(seed=None)\n",
    "\n",
    "# Perform a step in the game, i.e. send a text command and get the new state, a reward for reaching that new state and whether the game is finished (either won or lost).\n",
    "game_state, reward, done = env.step(command)\n",
    "\n",
    "# Display the current observation, i.e. send the interpreter's response to stdout.\n",
    "env.render()\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Getting the initial state"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "game_state = env.reset()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The variable `game_state` is a subclass of `textworld.core.GameState`. It provides the API allowing us to retrieve diverse information about the current state of the game. Here are the most useful properties."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Copyright (c) 1981, 1982, 1983 Infocom, Inc. All rights reserved.\n",
      "ZORK is a registered trademark of Infocom, Inc.\n",
      "Revision 88 / Serial number 840726\n",
      "\n",
      "West of House\n",
      "You are standing in an open field west of a white house, with a boarded front door.\n",
      "There is a small mailbox here.\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# Response from the parser after entering a text command or resetting a game.\n",
    "print(game_state.feedback)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "West of House\n",
      "You are standing in an open field west of a white house, with a boarded front door.\n",
      "There is a small mailbox here.\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# Text describing the room the player is currently in.\n",
    "# It corresponds the parser's feedback of the \"look\" command.\n",
    "print(game_state.description)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "You are empty-handed.\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# Text describing the player's inventory.\n",
    "print(game_state.inventory)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n"
     ]
    }
   ],
   "source": [
    "# Score received up until now.\n",
    "print(game_state.score)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Sending commands"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Opening the small mailbox reveals a leaflet.\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "game_state, score, done = env.step(\"open mailbox\")\n",
    "print(game_state.feedback)  # Result of the command."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "West of House\n",
      "You are standing in an open field west of a white house, with a boarded front door.\n",
      "There is a small mailbox here.\n",
      "The small mailbox contains:\n",
      "  A leaflet\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print(game_state.description)  # Description of the room."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Alternatively to `print(game_state.feedback)`, it is more convenient to do:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "West of House\n",
      "You are standing in an open field west of a white house, with a boarded front door.\n",
      "There is a small mailbox here.\n",
      "The small mailbox contains:\n",
      "  A leaflet\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "env.render()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Making a simple play loop"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Copyright (c) 1981, 1982, 1983 Infocom, Inc. All rights reserved.\n",
      "ZORK is a registered trademark of Infocom, Inc.\n",
      "Revision 88 / Serial number 840726\n",
      "\n",
      "West of House\n",
      "You are standing in an open field west of a white house, with a boarded front door.\n",
      "There is a small mailbox here.\n",
      "\n",
      "\n",
      "> open mailbox\n",
      "Opening the small mailbox reveals a leaflet.\n",
      "\n",
      "\n",
      "> take it\n",
      "Taken.\n",
      "\n",
      "\n",
      "> read it\n",
      "\"WELCOME TO ZORK!\n",
      "\n",
      "ZORK is a game of adventure, danger, and low cunning. In it you will explore some of the most amazing territory ever seen by\n",
      "mortals. No computer should be without one!\"\n",
      "\n",
      "\n",
      "\n",
      "Played 3 steps, scoring 0 points.\n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    done = False\n",
    "    env.reset()\n",
    "    while not done:\n",
    "        env.render()\n",
    "        command = input(\"> \")\n",
    "        game_state, reward, done = env.step(command)\n",
    "    \n",
    "    env.render()  # Final message.\n",
    "except KeyboardInterrupt:\n",
    "    pass  # Quit the game.\n",
    "\n",
    "print(\"Played {} steps, scoring {} points.\".format(game_state.moves, game_state.score))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Play a generated game\n",
    "TextWorld also has the capacity to generate games. Play one of our generated games below using the builtin play loop function or the `tw-play` script."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\n",
      "                    ________  ________  __    __  ________\n",
      "                   |        \\|        \\|  \\  |  \\|        \\\n",
      "                    \\$$$$$$$$| $$$$$$$$| $$  | $$ \\$$$$$$$$\n",
      "                      | $$   | $$__     \\$$\\/  $$   | $$\n",
      "                      | $$   | $$  \\     >$$  $$    | $$\n",
      "                      | $$   | $$$$$    /  $$$$\\    | $$\n",
      "                      | $$   | $$_____ |  $$ \\$$\\   | $$\n",
      "                      | $$   | $$     \\| $$  | $$   | $$\n",
      "                       \\$$    \\$$$$$$$$ \\$$   \\$$    \\$$\n",
      "              __       __   ______   _______   __        _______\n",
      "             |  \\  _  |  \\ /      \\ |       \\ |  \\      |       \\\n",
      "             | $$ / \\ | $$|  $$$$$$\\| $$$$$$$\\| $$      | $$$$$$$\\\n",
      "             | $$/  $\\| $$| $$  | $$| $$__| $$| $$      | $$  | $$\n",
      "             | $$  $$$\\ $$| $$  | $$| $$    $$| $$      | $$  | $$\n",
      "             | $$ $$\\$$\\$$| $$  | $$| $$$$$$$\\| $$      | $$  | $$\n",
      "             | $$$$  \\$$$$| $$__/ $$| $$  | $$| $$_____ | $$__/ $$\n",
      "             | $$$    \\$$$ \\$$    $$| $$  | $$| $$     \\| $$    $$\n",
      "              \\$$      \\$$  \\$$$$$$  \\$$   \\$$ \\$$$$$$$$ \\$$$$$$$\n",
      "\n",
      "\n",
      "\n",
      "-= Bedroom =-\n",
      "You are in a bedroom. A standard kind of place.\n",
      "\n",
      "You can make out a chest drawer. There's something strange about this being\n",
      "here, but you can't put your finger on it. You see a closed antique trunk right\n",
      "there by you. Look over there! a king-size bed. Now why would someone leave that\n",
      "there? But oh no! there's nothing on this piece of trash.\n",
      "\n",
      "There is a closed wooden door leading east.\n",
      "\n",
      "Done after 0 steps. Score 0/1.\n"
     ]
    }
   ],
   "source": [
    "textworld.play(\"./games/rewardsSparse_goalNone.ulx\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
